/************************************************************
   Copyright 2008 Abhinav Pobbati

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*************************************************************/

#pragma once

#pragma unmanaged
#include <Common/Base/Math/Vector/hkVector4.h>
#pragma managed

using Microsoft::Xna::Framework::Vector3;
using Microsoft::Xna::Framework::Vector4;

namespace Havok4Xna {
	
	ref class HkMatrix3;
	ref class HkTransform;
	ref class HkQsTransform;
	ref class HkRotation;

	public ref class HkVector4Comparison : public INativeReference {
	public:
		enum class Mask : int {
			None = hkVector4Comparison::MASK_NONE,
			W = hkVector4Comparison::MASK_W,
			Z = hkVector4Comparison::MASK_Z,
			ZW = hkVector4Comparison::MASK_ZW,

			Y = hkVector4Comparison::MASK_Y,
			YW = hkVector4Comparison::MASK_YW,
			YZ = hkVector4Comparison::MASK_YZ,
			YZW = hkVector4Comparison::MASK_YZW,

			X = hkVector4Comparison::MASK_X,
			XW = hkVector4Comparison::MASK_XW,
			XZ = hkVector4Comparison::MASK_XZ,
			XZW = hkVector4Comparison::MASK_XZW,

			XY = hkVector4Comparison::MASK_XY,
			XYW = hkVector4Comparison::MASK_XYW,
			XYZ = hkVector4Comparison::MASK_XYZ,
			XYZW = hkVector4Comparison::MASK_XYZW
		};

		void SetAnd(HkVector4Comparison ^a, HkVector4Comparison ^b);
		void Set(Mask m);
		hkBool32 AllAreSet(Mask m);
		hkBool32 AnyIsSet(Mask m);
		hkBool32 AllAreSet();
		hkBool32 AnyIsSet();
		int GetMask();
		int GetMask(Mask m);

	internal:
		HK_CLASS_INTERNALS(HkVector4Comparison,hkVector4Comparison)
	};

	public ref class HkVector4 : public INativeReference {
	public:
		HkVector4(float x, float y, float z, float w);
		HkVector4(float value);
		HkVector4(Vector3 vector);
		HkVector4(Vector4 vector);
		HkVector4(HkVector4 ^vector);

		void Set(float x, float y, float z);
		void Set(float x, float y, float z, float w);
		void SetAll(float val);
		void SetAll3(float val);
		void SetZero4();
		void Add4(HkVector4 ^v);
		void Add3ClobberW(HkVector4 ^v);
		void SetAdd4(HkVector4 ^a, HkVector4 ^b);
		void Sub4(HkVector4 ^v);
		void Sub3ClobberW(HkVector4 ^v);
		void SetSub4(HkVector4 ^a, HkVector4 ^b);
		void Mul4(HkVector4 ^a);
		void SetMul4(HkVector4 ^a, HkVector4 ^b);
		void Mul4(float a);
		void SetMul4(float a, HkVector4 ^b);
		void AddMul4(float a, HkVector4 ^b);
		void SubMul4(float a, HkVector4 ^b);
		void SetAddMul4(HkVector4 ^a, HkVector4 ^b, float r);
		void SetAddMul4(HkVector4 ^a, HkVector4 ^b, HkVector4 ^c);
		void SetCross(HkVector4 ^a, HkVector4 ^b);
		void SetInterpolate4(HkVector4 ^a, HkVector4 ^b, float r);
		hkBool32 Equals3(HkVector4 ^a, float epsilon);
		hkBool32 Equals4(HkVector4 ^a, float epsilon);
		HkVector4Comparison ^CompareLessThan4(HkVector4 ^v);
		HkVector4Comparison ^CompareEqual4(HkVector4 ^v);
		HkVector4Comparison ^CompareLessThanEqual4(HkVector4 ^v);
		HkVector4Comparison ^CompareLessThanZero4();
		HkVector4Comparison ^CompareGreaterThan4(HkVector4 ^v);
		HkVector4Comparison ^CompareGreaterThanEqual4(HkVector4 ^v);
		hkBool32 AllLessThan3(HkVector4 ^v);
		hkBool32 AllLessThan4(HkVector4 ^v);
		/*void Select32(HkVector4 ^a, HkVector4 ^b, HkVector4Comparison ^comp);*/
		void SetNeg3(HkVector4 ^v);
		void SetNeg4(HkVector4 ^v);
		void SetAbs4(HkVector4 ^v);
		void SetMin4(HkVector4 ^a, HkVector4 ^b);
		void SetMax4(HkVector4 ^a, HkVector4 ^b);
		void SetMul3(HkMatrix3 ^m, HkVector4 ^v);
		void SetRotatedDir(HkRotation ^r, HkVector4 ^v);
		void SetRotatedInverseDir(HkRotation ^r, HkVector4 ^v);
		void SetTransformedPos(HkTransform ^t, HkVector4 ^v);
		void SetTransformedInversePos(HkTransform ^t, HkVector4 ^v);
		void SetTransformedPos(HkQsTransform ^t, HkVector4 ^v);
		void SetTransformedInversePos(HkQsTransform ^t, HkVector4 ^v);
		float Dot3(HkVector4 ^v);
		float Dot3Fpu(HkVector4 ^v);
		float Dot4(HkVector4 ^v);
		float Dot4xyz1(HkVector4 ^v);
		float HorizontalAdd3();
		float HorizontalAdd4();
		float Length3();
		float LengthSquared3();
		float LengthInverse3();
		float DistanceTo3(HkVector4 ^v);
		float Length4();
		float LengthSquared4();
		float LengthInverse4();
		void Normalize3();
		float NormalizeWithLength3();
		void Normalize4();
		float NormalizeWithLength4();
		void FastNormalize3();
		float FastNormalizeWithLength3();
		void FastNormalize3NonZero();
		HkResult Normalize3IfNotZero();
		void SetXYZW(HkVector4 ^v1, HkVector4 ^v2);
		void SetW(HkVector4 ^v);
		void SetXYZ(HkVector4 ^v);
		void SetXYZ0(HkVector4 ^v);
		void SetReciprocal4(HkVector4 ^v);
		void SetReciprocal3(HkVector4 ^v);
		void SetSqrtInverse4(HkVector4 ^v);
		int GetMajorAxis();
		bool IsOk3();
		bool IsOk4();
		bool IsNormalized3(float eps);
		bool IsNormalized4(float eps);

		DECLARE_PROPERTY_GETSET(float, X)
		DECLARE_PROPERTY_GETSET(float, Y)
		DECLARE_PROPERTY_GETSET(float, Z)
		DECLARE_PROPERTY_GETSET(float, W)

	internal:
		HK_CLASS_INTERNALS(HkVector4,hkVector4)
	};
}